package com.ly.wxstore.service.goods;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.ly.wxstore.comm.Delete;
import com.ly.wxstore.comm.Error;
import com.ly.wxstore.comm.MyPage;
import com.ly.wxstore.comm.OrderStatus;
import com.ly.wxstore.comm.SalerLevel;
import com.ly.wxstore.entity.SalerUpHierarchy;
import com.ly.wxstore.entity.UserAddress;
import com.ly.wxstore.entity.fin.FinBrokerageRecord;
import com.ly.wxstore.entity.fin.FinBrokerageRecordLog;
import com.ly.wxstore.entity.fin.FinBrokerageStatistics;
import com.ly.wxstore.entity.fin.FinBrokerageStatisticsLog;
import com.ly.wxstore.entity.goods.Goods;
import com.ly.wxstore.entity.goods.GoodsDeliveryAddress;
import com.ly.wxstore.entity.goods.GoodsMarketingStrategy;
import com.ly.wxstore.entity.goods.GoodsOrder;
import com.ly.wxstore.entity.goods.GoodsOrderDetail;
import com.ly.wxstore.exception.ServerException;
import com.ly.wxstore.repository.SalerUpHierarchyDao;
import com.ly.wxstore.repository.fin.FinBrokerageRecordDao;
import com.ly.wxstore.repository.fin.FinBrokerageRecordLogDao;
import com.ly.wxstore.repository.fin.FinBrokerageStatisticsDao;
import com.ly.wxstore.repository.fin.FinBrokerageStatisticsLogDao;
import com.ly.wxstore.repository.goods.GoodsDao;
import com.ly.wxstore.repository.goods.GoodsMarketingStrategyDao;
import com.ly.wxstore.repository.goods.GoodsOrderDao;
import com.ly.wxstore.repository.goods.GoodsOrderDetailDao;
import com.ly.wxstore.service.UserAddressService;
import com.ly.wxstore.service.weixin.WeixinConf;
import com.ly.wxstore.service.weixin.WeixinPublicService;
import com.ly.wxstore.vo.OrderVo;
import com.ly.wxstore.web.OrderController;

/**
 * 
 * 
 * @author Peter
 */
// Spring Service Bean的标识.
@Component
public class GoodsOrderService {

	private static Logger logger = LoggerFactory.getLogger(OrderController.class);

	@Autowired
	private GoodsOrderDao goodsOrderDao;

	@Autowired
	private GoodsDao goodsDao;

	@Autowired
	private GoodsOrderDetailDao goodsOrderDetailDao;

	@Autowired
	private GoodsMarketingStrategyDao goodsMarketingStrategyDao;

	@Autowired
	private SalerUpHierarchyDao salerUpHierarchyDao;

	@Autowired
	private FinBrokerageStatisticsDao finBrokerageStatisticsDao;

	@Autowired
	private FinBrokerageStatisticsLogDao finBrokerageStatisticsLogDao;

	@Autowired
	private FinBrokerageRecordDao finBrokerageRecordDao;

	@Autowired
	private FinBrokerageRecordLogDao FinBrokerageRecordLogDao;

	@Autowired
	private OrderCodeService orderCodeService;

	@Autowired
	private UserAddressService userAddressService;

	@Autowired
	private WeixinConf weixinConf;

	@Autowired
	private WeixinPublicService weixinPublicService;

	public GoodsOrder getById(Long id) {
		return goodsOrderDao.getById(id);
	}

	public List<GoodsOrder> getAll() {
		return goodsOrderDao.getAll();
	}

	/**
	 * 分页查询
	 * 
	 * @param overtime
	 * @param pageStart
	 * @param pageSize
	 * @return
	 */
	public MyPage<GoodsOrder> searchPage(GoodsOrder goodsOrder, int currentPage, int pageSize) {
		MyPage<GoodsOrder> myPage = new MyPage<GoodsOrder>();

		Long count = goodsOrderDao.searchCount(goodsOrder);

		int pageStart = (currentPage - 1) < 0 ? 0 : (currentPage - 1) * pageSize;
		List<GoodsOrder> list = goodsOrderDao.searchPage(goodsOrder, pageStart, pageSize);

		myPage.setCount(count);
		myPage.setContent(list);

		return myPage;
	}

	public void save(GoodsOrder goodsOrder) {
		goodsOrderDao.save(goodsOrder);
	}

	public void update(GoodsOrder goodsOrder) {
		goodsOrderDao.update(goodsOrder);
	}

	/**
	 * 软删除
	 */
	public void delete(Long id) {
		goodsOrderDao.delete(id);
	}

	// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	/**
	 * 
	 * 创建【未付款】订单（怎么验证订单数据的正确性？订单在支付之前创建，支付后，支付金额需要与订单实付金额进行比较。）
	 * 
	 * <p>
	 * 保存7个表：1订单、2订单详情、3售后地址、4佣金记录、5佣金记录log、6佣金统计、7佣金统计log
	 * </p>
	 * 
	 * @param goodsOrder
	 * @return BrandWCPayRequestVo
	 * @throws ServerException
	 */
	@Transactional(readOnly = false)
	public GoodsOrder createOrder(GoodsOrder goodsOrder) throws ServerException {

		// 1. 创建订单
		// GoodsOrder order = new GoodsOrder();
		// 创建订单编号
		String orderCode = orderCodeService.getOrderCode();
		goodsOrder.setCreateDate(new Date());
		goodsOrder.setDeleted(Delete.Enabled);
		goodsOrder.setOrderCode(orderCode);
		goodsOrder.setWeixinPublicId(weixinConf.getPublicId());
		// goodsOrder.setMoney(goodsOrder.getMoney());// 订单金额
		// goodsOrder.setRealMoney(goods.getRealPrice());// 实付金额
		goodsOrder.setOrderStatus(OrderStatus.UNPAY);// 【未付款】（支付成功后才能改为‘已付款’）
		goodsOrder.setUpdateDate(new Date());
		goodsOrderDao.save(goodsOrder);

		// 2. 处理并保存订单详情
		List<GoodsOrderDetail> detailList = goodsOrder.getGoodsList();
		if (detailList != null && detailList.size() > 0) {
			for (int i = 0; i < detailList.size(); i++) {
				GoodsOrderDetail detail = detailList.get(i);
				Goods goods = goodsDao.getById(detail.getGoodsId());
				detail.setGoodsDesc(goods.getGoodsDesc());
				detail.setGoodsId(goods.getId());
				detail.setGoodsName(goods.getGoodsName());
				// detail.setGoodsNumber(1);//页面传入商品数量
				detail.setOrderCode(orderCode);// 订单编号
				detail.setRealPrice(goods.getRealPrice());// 实际销售价格
				detail.setCostPrice(goods.getCostPrice());// 成本
				detail.setPrice(goods.getPrice());// 售价（折前价格）
				detail.setTotal(detail.getRealPrice() * detail.getGoodsNumber());// 合计
				detail.setGoodsImageUrl(goods.getGoodsImageUrl());
				
				goodsOrderDetailDao.save(detail);
			}
		} else {
			throw new ServerException(Error._30002, Error._30002_MSG);
		}

		// 3. 设置收货地址
		if (goodsOrder.getGoodsDeliveryAddress() == null) {
			throw new ServerException(Error._30004, Error._30004_MSG);
		}
		Long addressId = goodsOrder.getGoodsDeliveryAddress().getId();
		UserAddress address = userAddressService.getById(addressId);
		if (address != null) {
			GoodsDeliveryAddress delAddr = changeToGoodsDeliveryAddress(orderCode, address);
			goodsOrder.setGoodsDeliveryAddress(delAddr);
		} else {
			throw new ServerException(Error._30003, Error._30003_MSG);
		}

		// -------------------------------------- 处理佣金
		// -------------------------------------------
		// 佣金和积分使用组件式扩展，不在此硬编码，切记！~~，并且需要用户选择是否使用积分系统，积分规则给予用于一定的选择。
		// 4. 创建佣金记录、log 以及 佣金统计 和 log
		// processBrokerage(goodsOrder);

		

		return goodsOrder;
	}


	// 创建佣金记录、log 以及 佣金统计 和 log （目前只支持一个商品）
	private void processBrokerage(GoodsOrder goodsOrder) {
		SalerUpHierarchy salerUpHierarchy = salerUpHierarchyDao.getUpHierarchyBySid(goodsOrder.getCreateSid());

		// 获取商品佣金提成策略

		if (salerUpHierarchy != null) {
			String level_1_sid = salerUpHierarchy.getUpLevel1Sid();// 父级（上1级）
			String level_2_sid = salerUpHierarchy.getUpLevel2Sid();// 爷爷级（上2级）
			String level_3_sid = salerUpHierarchy.getUpLevel3Sid();// 祖父级（上3级）

			List<GoodsOrderDetail> list = goodsOrder.getGoodsList();
			int goodsNumber = list.get(0).getGoodsNumber();// 商品数量
			GoodsMarketingStrategy goodsMarketingStrategy = goodsMarketingStrategyDao.getByGoodsId(list.get(0).getGoodsId());

			// 父级（上1级）新增佣金记录、修改佣金统计
			if (StringUtils.isNotBlank(level_1_sid)) {
				// 佣金记录
				Double brokerageRate = goodsMarketingStrategy.getLevelOneBrokerage();// 一个商品的佣金

				Double brokerage = brokerageRate * goodsNumber;

				FinBrokerageRecord finBrokerageRecord1 = new FinBrokerageRecord();
				finBrokerageRecord1.setBrokerage(brokerage);// 佣金*商品数量
				finBrokerageRecord1.setBrokerageStatus(goodsOrder.getOrderStatus());
				finBrokerageRecord1.setCreateDate(new Date());
				finBrokerageRecord1.setInSid(level_1_sid);// 收益人sid
				finBrokerageRecord1.setLevel(SalerLevel.LEVEL_1);
				finBrokerageRecord1.setOrderCode(goodsOrder.getOrderCode());
				finBrokerageRecord1.setOrderMoney(goodsOrder.getRealMoney());// 实际订单价格
				finBrokerageRecord1.setOutSid(goodsOrder.getCreateSid());// 付款人sid
				finBrokerageRecord1.setWeixinPublicId(weixinConf.getPublicId());
				finBrokerageRecordDao.save(finBrokerageRecord1);
				FinBrokerageRecordLogDao.save(changeToLog(finBrokerageRecord1));

				// 保存或更新 佣金统计 和 log
				processBrokerageStatistics(level_1_sid, brokerageRate);
			}

			// 爷爷级（上2级）新增佣金记录、修改佣金统计
			if (StringUtils.isNotBlank(level_2_sid)) {
				FinBrokerageRecord finBrokerageRecord2 = new FinBrokerageRecord();
				Double brokerageRate = goodsMarketingStrategy.getLevelTwoBrokerage();// 佣金

				Double brokerage = brokerageRate * goodsNumber;

				finBrokerageRecord2.setBrokerage(brokerage);// 佣金
				finBrokerageRecord2.setBrokerageStatus(OrderStatus.UNPAY);
				finBrokerageRecord2.setCreateDate(new Date());
				finBrokerageRecord2.setInSid(level_2_sid);// 收益人sid
				finBrokerageRecord2.setLevel(SalerLevel.LEVEL_2);
				finBrokerageRecord2.setOrderCode(goodsOrder.getOrderCode());
				finBrokerageRecord2.setOrderMoney(goodsOrder.getRealMoney());// 实际订单价格
				finBrokerageRecord2.setOutSid(goodsOrder.getCreateSid());// 付款人sid
				finBrokerageRecord2.setWeixinPublicId(weixinConf.getPublicId());
				finBrokerageRecordDao.save(finBrokerageRecord2);
				FinBrokerageRecordLogDao.save(changeToLog(finBrokerageRecord2));

				// 保存或更新 佣金统计 和 log
				processBrokerageStatistics(level_2_sid, brokerage);

			}

			// 祖父级（上3级）新增 佣金记录、修改佣金统计
			if (StringUtils.isNotBlank(level_3_sid)) {
				FinBrokerageRecord finBrokerageRecord3 = new FinBrokerageRecord();
				Double brokerageRate = goodsMarketingStrategy.getLevelThreeBrokerage();// 佣金

				Double brokerage = brokerageRate * goodsNumber;

				finBrokerageRecord3.setBrokerage(brokerage);// 佣金
				finBrokerageRecord3.setBrokerageStatus(OrderStatus.UNPAY);
				finBrokerageRecord3.setCreateDate(new Date());
				finBrokerageRecord3.setInSid(level_3_sid);// 收益人sid
				finBrokerageRecord3.setLevel(SalerLevel.LEVEL_3);
				finBrokerageRecord3.setOrderCode(goodsOrder.getOrderCode());
				finBrokerageRecord3.setOrderMoney(goodsOrder.getRealMoney());// 实际订单价格
				finBrokerageRecord3.setOutSid(goodsOrder.getCreateSid());// 付款人sid
				finBrokerageRecord3.setWeixinPublicId(weixinConf.getPublicId());
				finBrokerageRecordDao.save(finBrokerageRecord3);
				FinBrokerageRecordLogDao.save(changeToLog(finBrokerageRecord3));

				// 保存或更新 佣金统计 和 log
				processBrokerageStatistics(level_3_sid, brokerage);
			}
		}
	}

	private GoodsDeliveryAddress changeToGoodsDeliveryAddress(String orderCode, UserAddress address) {
		GoodsDeliveryAddress delAddr = new GoodsDeliveryAddress();
		delAddr.setId(address.getId());
		delAddr.setArea(address.getArea());
		delAddr.setCity(address.getCity());
		delAddr.setCountry(address.getCountry());
		delAddr.setDetail(address.getDetail());
		delAddr.setName(address.getName());
		delAddr.setOrderCode(orderCode);
		delAddr.setPhone(address.getPhone());
		delAddr.setProvince(address.getProvince());
		delAddr.setStreet(address.getStreet());
		delAddr.setZip(address.getZip());
		return delAddr;
	}

	/**
	 * 保存或更新 佣金统计 和 log
	 * 
	 * @param goodsMarketingStrategy
	 * @param level_1_sid
	 * @param brokerage
	 */
	private void processBrokerageStatistics(String level_1_sid, Double brokerage) {
		// 佣金统计
		FinBrokerageStatistics finBrokerageStatistics = finBrokerageStatisticsDao.getBySid(level_1_sid);
		// 新建佣金统计
		if (finBrokerageStatistics == null) {
			finBrokerageStatistics = new FinBrokerageStatistics();
			finBrokerageStatistics.setApplayRefundBrokerage(0.0);// 申请退款佣金
			finBrokerageStatistics.setBrokerage(0.0);// 可提现佣金(收货7天后)
			finBrokerageStatistics.setCancelBrokerage(0.0);// 取消订单佣金
			finBrokerageStatistics.setCreateDate(new Date());
			finBrokerageStatistics.setPayedBrokerage(0.0);// 已付款订单佣金(待发货、待收货)
			finBrokerageStatistics.setReceivedBrokerage(0.0);// 已收货订单佣金(收货7天内)
			finBrokerageStatistics.setRefundBrokerage(0.0);// 已退款佣金
			finBrokerageStatistics.setSid(level_1_sid);
			finBrokerageStatistics.setUnpayBrokerage(brokerage);// 未付款订单佣金-----------------------------
																// check now--
			finBrokerageStatistics.setUpdateDate(new Date());
			finBrokerageStatistics.setWaitAuditBrokerage(0.0);// 待审核提现佣金
			finBrokerageStatistics.setWeixinPublicId(weixinConf.getPublicId());
			finBrokerageStatistics.setWithdrawBrokerage(0.0);// 已提现佣金

			finBrokerageStatisticsDao.save(finBrokerageStatistics);

		} else {// 修改佣金统计
			Double old_unpayBrokerage = finBrokerageStatistics.getUnpayBrokerage();// 原来的佣金
			if (old_unpayBrokerage == null) {
				old_unpayBrokerage = 0.0;
			}
			Double new_unpayBrokerage = old_unpayBrokerage + brokerage;// 新的佣金

			finBrokerageStatistics.setUnpayBrokerage(new_unpayBrokerage);
			finBrokerageStatistics.setUpdateDate(new Date());
			finBrokerageStatisticsDao.update(finBrokerageStatistics);
		}

		finBrokerageStatisticsLogDao.save(changeToStaticLog(finBrokerageStatistics));
	}

	private FinBrokerageStatisticsLog changeToStaticLog(FinBrokerageStatistics finBrokerageStatistics) {
		FinBrokerageStatisticsLog log = new FinBrokerageStatisticsLog();
		log.setApplayRefundBrokerage(finBrokerageStatistics.getApplayRefundBrokerage());
		log.setBrokerage(finBrokerageStatistics.getBrokerage());
		log.setCancelBrokerage(finBrokerageStatistics.getCancelBrokerage());
		log.setCreateDate(new Date());
		log.setPayedBrokerage(finBrokerageStatistics.getPayedBrokerage());
		log.setReceivedBrokerage(finBrokerageStatistics.getReceivedBrokerage());
		log.setRefundBrokerage(finBrokerageStatistics.getRefundBrokerage());
		log.setSid(finBrokerageStatistics.getSid());
		log.setUnpayBrokerage(finBrokerageStatistics.getUnpayBrokerage());
		log.setWaitAuditBrokerage(finBrokerageStatistics.getWaitAuditBrokerage());
		log.setWeixinPublicId(finBrokerageStatistics.getWeixinPublicId());
		log.setWithdrawBrokerage(finBrokerageStatistics.getWithdrawBrokerage());

		return log;
	}

	/**
	 * 根据FinBrokerageRecord创建FinBrokerageRecordLog对象
	 * 
	 * @param finBrokerageRecord
	 * @return FinBrokerageRecordLog
	 */
	private FinBrokerageRecordLog changeToLog(FinBrokerageRecord finBrokerageRecord) {
		FinBrokerageRecordLog log = new FinBrokerageRecordLog();
		log.setBrokerage(finBrokerageRecord.getBrokerage());
		log.setBrokerageStatus(finBrokerageRecord.getBrokerageStatus());
		log.setCreateDate(finBrokerageRecord.getCreateDate());
		log.setInSid(finBrokerageRecord.getInSid());
		log.setLevel(finBrokerageRecord.getLevel());
		log.setOrderCode(finBrokerageRecord.getOrderCode());
		log.setOrderMoney(finBrokerageRecord.getOrderMoney());
		log.setOutSid(finBrokerageRecord.getOutSid());
		log.setWeixinPublicId(finBrokerageRecord.getWeixinPublicId());
		return log;
	}

	/**
	 * 创建订单，实际数据库中没有创建订单，用户点击支付按钮(确认订单)时才真正在数据库创建订单。
	 * 
	 * @param sid
	 * @param openid
	 * @param goodsId
	 * @return
	 */
	public GoodsOrder preOrder(String sid, String openid,List<OrderVo> orderVoList) {

		GoodsOrder order = new GoodsOrder();

		// 2. 收货地址
		UserAddress address = userAddressService.getDefaultBySid(sid);
		if (address != null) {
			GoodsDeliveryAddress delAddr = changeToGoodsDeliveryAddress(null, address);
			order.setGoodsDeliveryAddress(delAddr);
		}

		// 3. 商品详情
		for(OrderVo orderVo : orderVoList){
			Goods goods = goodsDao.getById(orderVo.getGoodsId());
			GoodsOrderDetail detail = new GoodsOrderDetail();
			detail.setGoodsDesc(goods.getGoodsDesc());
			detail.setGoodsId(goods.getId());
			detail.setGoodsName(goods.getGoodsName());
			detail.setGoodsNumber(orderVo.getGoodsNumber());
			// detail.setOrderCode(orderCode); //未创建订单，不需要创建订单编号
			detail.setRealPrice(goods.getRealPrice());// 实际销售价格 
			// detail.setCostPrice(goods.getCostPrice());// 成本 页面不显示成本
			detail.setPrice(goods.getPrice());// 售价（折前价格）
			detail.setCartId(orderVo.getCartId());
			detail.setGoodsImageUrl(goods.getGoodsImageUrl());
			
			order.getGoodsList().add(detail);
		}
		// order.setMoney(detail.getPrice()); //其get方法根据detail自动计算
		// order.setRealMoney(detail.getRealPrice());//其get方法根据detail自动计算

		return order;
	}

	public List<GoodsOrder> getByOpenid(String openid) {
		return goodsOrderDao.getByOpenid(openid);
	}

	public void changeOrderStatus(String updateSid, Long orderId, Long orderStatus) {
		GoodsOrder order = new GoodsOrder();
		
		order.setId(orderId);
		order.setOrderStatus(orderStatus);
		order.setUpdateDate(new Date());
		order.setUpdateSid(updateSid);
		goodsOrderDao.update(order);
		
	}

}
